Translated by visionNoob, KNU https://github.com/insurgent92/CS231N_17_KOR_SUB
CS231N 3강입니다.
오늘은 손실함수(Loss functions)와 최적화(Optimization)을 배울겁니다.
진도 나가기에 앞서 공지사항을 전달합니다.
먼저, 첫 번째 과제가 생겼습니다.
웹사이트에서 확인하실 수 있습니다.
과제를 좀 늦게 내드렸기 때문에
4월 20일 목요일 오후 11시 59분으로 기한을 변경합니다.
앞으로 2주정도 라고 보시면 됩니다.
그리고 변경된 기한으로 강의계획서를 업데이트하겠습니다.
과제를 완료하면 zip파일로 Canvas에 업로드해야 하며
가능한 빨리 채점을 하도록 하겠습니다.
다음 사항은 여러분이 공지사항을 확인하려면 항상 Piazza를 체크해야 한다는 것입니다.
이번주에 Piazza에 몇가지 예제 프로젝트를 공고해 놓을 것입니다.
그래서 Stanford 커뮤니티와, 혹은 Stanford와 연계된 분들로부터 프로젝트 아이디와 관련된 예시를 부탁드렸는데,
그리고 그 분들이 이 수업을 듣는 학생들과 함께 프로젝트를 진행하고 싶다는 제안을 해주셨습니다.
그러니 Piazza에 공고를 확인해 보시고
하고싶은 프로젝트가 있으면 자유롭게 프로젝트 멘토와 직접 얘기하면 되겠습니다.
추가적으로 강의 홈피에 근무시간을 게시하였습니다.
구글 캔린더로 게시하였고 학생들이 근무시간에 대해 많이 물어봐서 이번에 게시하였습니다.
마지막 공지는 구글 클라우드 관련된 것입니다.
구글 클라우드에서 우리 강의를 지원하므로
여러분의 과제와 프로젝트를 수행하기 위해 구글 클라우드 크래딧 100$를 지급하였으며
사용하는 방법은 추후 Piazza에 공지하겠습니다.
공지사항에 대한 질문이 없으면 진도를 나가겠습니다.
좋습니다.
저번 2강을 복습해보면
인식에서의 어려운 점을 살펴보았고
데이터 중심의 방식에 초점을 마춰보았습니다.
그리고 이미지 분류에 대해 배웠고 왜 이미지 분류가 어려운지, 그리고
컴퓨터가 보는것과 사람이 보는 것의 차이가 있다는 것도 배웠습니다.
그리고 분류를 어렵게하는 조명의 변화, 변형에 대해 다뤘고 왜 이게 그토록 어려운지에 대해 배웠습니다.
인간의 시각체계는 이 일을 엄청 쉽게 하는데도 말이죠
그리고 KNN 분류기도 배웠습니다.
데이터 중심 접근방법 중에 가장 단순한 방법이었죠.
그리고 CIFAR-10도 배웠습니다. 저기 좌상단에 보이는 이미지들이죠.
CIFAR-10은 비행기, 자동차 등 10개의 카테고리가 있습니다.
그리고 어떻게 KNN을 이용해서 학습 데이터를 가지고 각 카테고리 클래스를 분류하는
결정 경계를 학습시킬 수 있는지도 배웠습니다.
또한 크로스 벨리데이션데 대해서도 배웠고 트레인, 벨리데이션, 테스트셋으로 나눠서 하이퍼파라미터를 찾는 법도 배웠습니다.
그리고 2강 마지막에는 Linear classification에 대해 배웠 습니다. Linear classifier는 뉴럴넷의 기본요소입니다.
Linear classifier는 parametric classifier의 일종입니다. parametric classifier라는 것은
트레이닝 데이터의 정보가 파라미터인 "행렬 W"로 요약된 다는 것을 뜻합니다. 그리고 W가 학습되는 것입니다.
그리고 이 Linear classifier는 상당히 간단합니다.
이미지를 입력받으면 하나의 긴 벡터로 폅니다.
여기 이미지 x가 있고,
이 이미지는 32x32x3 픽셀이고, 이를 긴 열벡터로 펼치게 됩니다.
32x32는 이미지의 높이와 너비이며 3은 이미지의 채널 red, green, blue 입니다.
그리고 파라미터 "행렬 W"가 있는데
이 행렬은 아까 만들었던 이미지 픽셀과 연산하여
CIFAR-10의 각 10개의 클래스에 해당하는 클래스 스코어를 만들어줍니다.
그리고 해석해보면 스코어가 더 큰 값은
가령 고양이 클래스의 스코어가 더 크다는 것은 분류기가 이 이미지가 고양이일것 같다고 생각하는 것입니다.
반대로 개나 자동차 클래스의 스코어가 더 낮다는 것은 이 이미지가 개나 자동차일 확률이 낮다는 것을 의미하는 것입니다.
또한 지난 수업에서 설명이 좀 부족했던 부분이 있었습니다. Linear clssification을 각 클래스 템플릿으로 보는 것인데
좌하단의 다이어그램을 보시면, 행렬 W에는 각 10개의 클래스와 이미지의 모든 픽셀에 대응되는 하나씩의 요소가 있습니다.
그리고 이 것은 "이 픽셀이 클래스를 결정하는데 얼마나 중요한 역할을 하는지"를 의미합니다.
행렬 W의 각 행들이 해당하는 그 클래스의 템플릿이 되는 것입니다.
행렬 W의 각 행은 "이미지의 픽셀 값"과 "해당 클래스" 사이의 가중치가 되기 때문에
그렇기 때문에 우리가 각 행을 풀어서 다시 한 이미지로 재구성하면 각 클래스에 대응하는 학습된 템플릿을 볼 수 있었습니다.
그리고 또한 Linear clssification이 고차원 공간에서의 일종의 "결정 경계"를 학습한다는 측면으로 볼 수 있는데,
그 공간의 차원은 이미지의 픽셀 값에 해당하는 것입니다.
지난 시간에 여기까지 진행했습니다.
지난 시간에는 Linear classifier에 대한 간략한 아이디어만 배우고 끝났습니다.
그때는 실제로 행렬W를 어떻게 만드는지는 다루지 않았습니다.
가장 좋은 행렬W를 구하는데 어떻게 트레이닝 데이터를 활용해야 하는지는 언급하지 않았었습니다.
지난 시간에는 임의의 행렬 W를 사용했었고,
그 행렬 W를 가지고 각 이미지에 해당하는 10개의 클래스 스코어를 계산하였습니다.
이 때의 클래스 스코어는 좋을수도, 나쁠수도 있었습니다. (임의로 정한 것이니까)
여기 간단한 예시가 있는데 세개의 트레이닝 데이터에 대한
임의의 행렬W를 가지고 예측한 10개의 클래스 스코어입니다.
굵게 표시한 각 스코어를 보면 더 좋은것도 있고 나쁜 것도 있다는 것을 볼 수 있습니다.
예컨데 왼쪽의 이미지를 보면 고양이이죠 우리는 인간이니까 아주 쉽게 알 수 있죠.
하지만 고양이에 부여된 확률을 보면, (확률이 아니라 스코어죠)
이 분류기가 cat에는 2.9점을 줬습니다.
반면 frog에는 3.78점을 줬군요
이 분류기는 별로 좋아보이지 않습니다. 우리는 정답 클래스(고양이) 가 가장 높은 점수가 되는 분류기를 원합니다.
반면 다른 예를 살펴봅시다. 자동차를 보면
자동차 이미지에서는 자동차의 스코어가 제일 높습니다. 좋은 거죠
개구리의 예를 보면 스코어가 -4입니다. 오히려 다른 스코어보다도 훨씬 낮습니다. 엄청 안좋은 것입니다.
이렇게 분석하는 방법은 좋지 않습니다.
스코어를 눈으로 훑으면서 어느게 좋고 어느게 나쁜지 살펴보기만 하는것은 좋은 생각이 아닙니다.
이런 알고리즘을 만들고, 어떤 W가 가장 좋은지를 결정하기 위해서는
지금 만든 W가 좋은지 나쁜지를 정량화 할 방법이 필요합니다.
W를 입력으로 받아서 각 스코어를 확인하고 이 W가 지금 얼마나 거지같은지를 정량적으로 말해주는 것이 바로 손실함수입니다.
이번 강의에서는 Image classification에서 쓸만한 몇가지 손실함수를 소개해 드리도록 하겠습니다.
손실함수가 어떤 일을 해야하는지 한번 생각해 보세요.
임의의 값 W가 얼마나 좋은지 나쁜지를 정량화해 줘야 합니다.
우리가 실제로 원하는 것은, 행렬 W가 될 수 있는 모든 경우의 수에 대해서
"가장 덜 구린" W가 무엇인지를 찾고싶은 것입니다.
이 과정이 바로 "최적화 과정" 이며
최적화에 대해서는 좀 있다가 다시 다루겠습니다.
일단 문제를 좀 줄여보겠습니다. 클래스 10개는 다루기가 불편하니깐요
이번 강의에서는 클래스를 3개로 하는 toy 데이터셋을 사용하겠습니다.
이 예제에서 "고양이" 클래스는 잘 분류되지 못했고 "자동차" 는 잘됐고 "개구리"는 최악입니다. 개구리 점수는 다른 것보다 더 낮습니다.
이를 좀 더 공식화해 봅시다. 손실 함수에 대해 생각해보면
트레이닝 데이터 X와 Y가 있고
보통 X는 알고리즘의 입력에 해당하고
Image classification 알고리즘이라면 X는 이미지가 될 것이고 Y는 예측하고자 하는 것이 될 것입니다.
보통은 Y는 레이블이나 타겟이라고 합니다.
Image classification의 경우라면 각 이미지를 CIFAR-10 의 10개의 카테고리 중 하나로 분류하는 것이고,
여기에서 레이블 y는 1에서 10 사이의 정수 값이 됩니다. 프로그래밍 언어에 따라 0에서 9 일수도 있습니다.
어쨌든 이 y라는 정수값은 각 이미지 x의 정답 카테고리를 의미합니다.
앞서 예측 함수를 정의했었죠 입력 이미지 x와 행렬 W를 입력으로 받아서 y를 예측하는 것입니다.
Image classification 문제라면 y는 10개가 되겠습니다. (CIFAR-10의 경우)
그 다음 손실함수 L_i를 정의합니다.
앞서 말씀드린 예측함수 f와 정답 값 Y를 입력으로 받아서는
이 트레이닝 샘플을 얼마나 구리게 예측하는지를 정량화 시켜 줍니다.
그리고 최종 Loss인 "L"은 우리 데이터 셋에서 각 N개의 샘플들의 Loss의 평균이 됩니다.
이 함수는 아주 일반적인 공식입니다.
그리고 Image classification 외에도 다양하게 확장할 수 있습니다.
좀 더 나아가서 다른 딥러닝 알고리즘을 살펴보자면 어떤 알고리즘이던 가장 일반적으로 진행되는 일은,
일단 어떤 X와 Y가 존재하고, 여러분이 만들 파라미터 W에 W가 얼마나 좋은지를 정량화하는 손실 함수를 만드는 것입니다.
결국은 W의 공간을 탐색하면서 의트레이닝 데이터의 Loss를 최소화하는 어떤 W를 찾게 될 것입니다.
구체적으로 한 손실함수의 예를 들어보겠습니다. 이 손실함수는 Image classification에 아주 적합하기도 합니다.
multi-class SVM loss를 대해 알아보겠습니다.
아마 CS229에서 이진 SVM(Support Vector Machine) 본 적이 있을 것입니다.
multi-class SVM은 여러 클래스를 다루기 위한 이진 SVM의 일반화된 형태입니다.
CS229에서 다뤘던 이진 SVM은 두개의 클래스만 다룹니다.
각 데이터는 Positive 또는 Negative로 분류될 뿐입니다.
하지만 여긴 10개의 카테고리가 있기 때문에 여러개의 클래스를 다루려면 이 개념을 좀더 일반화 시켜야 합니다.
그렇기 때문에 multi-class SVM의 손실함수는 조금 재밌게 생겼습니다.
지금부터는 이에 대해 좀 더 자세히 알아보도록 하겠습니다.
각각의 트레이닝 데이터에서 Loss L_i 를 구하는 방법 부터 살펴보겠습니다.
L_i를 구하기 위해 우선 "True인 카테고리" 를 제외한 "나머지 카테고리 Y"의 합을 구합니다.
다시말해 맞지 않는 카테고리를 전부 합치는 것입니다.
그리고 올바른 카테고리의 스코어와 올바르지 않은 카테고리의 스코어를 비교해 봅니다.
만약 올바른 카테고리의 점수가 올바르지 않은 카테고리의 점수보다 더 높으면
그리고 그 격차가 일정 마진(safety margin) 이상이라면, 이 예시에서는 그 마진을 1로 두었죠
이 경우는 True인 스코어가 다른 false 카테고리보다 훨씬 더 크다는 것을 의미합니다.
그렇게 되면 Loss는 0이 됩니다.
이미지 내 정답이 아닌 카테고리의 모든 값들을 합치면
그 값이 바로 한 이미지의 최종 Loss 가 되는 것입니다.
그리고 전체 트레이닝 데이터 셋에서 그 Loss들의 평균을 구합니다.
이걸 수식화 시키면 if-then 으로 표현 할 수 있습니다. (if:)정답 클래스의 스코어의 점수가 제일 높으면
그럼 "then" 은 다음과 같이 나타낼 수 있습니다. then, max(0,s_j - s_yj + 1).
그리고 수식을 보다가 헷갈리 때가 있는데
그러면 직접 손으로 써보면서 이해하면 도움이 됩니다.
그리고 0과 다른 값의 최댓값, Max(0, value) 과 같은 식으로 손실 함수를 만드는데,
이런 류의 손실 함수를 "hinge loss"(경첩)라고 부르기도 합니다. 그래프의 모양때문에 붙혀진 이름입니다.
여기에서 x축은 S_Yi입니다. 실제 정답 클래스의 스코어입니다.
그리고 y축은 Loss입니다.
정답 카테고리의 점수가 올라갈수록 Loss가 선형적으로 줄어드는 것을 알 수 있습니다.
이 로스는 0이 된 이후에도 Safety margin 을 넘어설 때 까지 더 줄어듭니다.
Loss가 0이 됐다는 건 클래스를 잘 분류했다는 뜻입니다.
질문 있나요?
[죄송합니다만, S_Yi가 뭔가요?]
[정답 스코어인가요? ]
네 질문은
S가 어떤 것이고 S_Yi가 어떤 것인지 입니다.
S는 분류기의 출력으로 나온 예측된 스코어 입니다.
가령 1이 고양이고 2가 개면 S_1은 고양이 스코어 S_2는 개 스코어 인 것이죠
Y_i는 이미지의 실제 정답 카테고리 입니다. 정수 값이죠
그러니 S_Y_i는 트레이닝 셋의 i번째 이미지의 정답 클래스의 스코어인 것입니다.
질문 있으십니까?
[질문 중]
질문은, 그럼 정확히 무엇을 계산하는 것인지 입니다.
무엇을 계산하는지는 흥미로운 주제입니다. 앞으로 예제를 살펴보면 답을 찾을 수 있을 것입니다.
이 Loss가 말하고자 하는 것은 정답 스코어가 다른 스코어들보다 높으면 좋다는 것입니다.
정답 스코어는 safty margin(여기에서 1) 을 두고 다른 스코어들 보다 훨씬 더 높아야 합니다.
충분히 높지 않으면 Loss가 높아지게 됩니다.
3개의 트레이닝 데이터셋을 가지고 예를 들어보면 좀 더 감을 익힐 수 있을 것입니다.
여기서는 case space notation을 제거하고 zero one notation을 사용했습니다.
맨 왼쪽의 예시를 보면서 multi-class SVM loss가 계산 되는 과정을 살펴보자면
우선 정답이 아닌 클래스를 순회합니다.
Cat은 정답 클래스이니, Car와 Flog 클래스를 순회합니다. 이제 다시 Car의 경우를 살펴보면
이제 (Car 스코어) 5.1 - (Cat 스코어) 3.2 + 1(magin) 을 구합니다. Cat과 Car를 비교할때 짐작할 수 있는 것은
Car가 Cat보다 더 높으니까 Loss가 발생할 것이라는 것입니다.
이 고양이 이미지의 예시를 보면
2.9의 손실이 발생합니다. Cat-Car 와 Car-Flog를 비교해보면
Car는 3.2, Flog는 -1.7의 에러가 발생합니다.
Cat 스코어는 Frog 스코어보다 훨씬 그므로 Loss는 0이라고 할 수 있습니다.
고양이 이미지의 Multiclass-SVM Loss는 이런 클래스쌍의 Loss의 합이 되며
즉 2.9 + 0 = 2.9 가 되는 것입니다.
여기에서 2.9라는 숫자가 "얼마나 분류기가 이 이미지를 구리게 분류하는지" 에 대한 척도가 되겠습니다.
이런 작업은 여러번 반복합니다. Car 클래스에 다시한번 해보면
Car와 Cat을 비교해 볼 것입니다. Car 스코어가 Cat 스코어보다 높기 때문에 여기에서 Loss는 0이 될 것입니다.
Car 와 Frog도 비교해보면 Car의 스코어가 Frog보다 훨씬 더 크다는 것을 알 수 있습니다.
그러므로 Car 의 경우는 전체 Loss도 0이 되겠습니다.
이미 다들 감을 잡으셨겠지만 개구리, frog의 경우도 한번 봅시다.
Frog와 Cat을 보면 엄청 큰 Loss가 발생함을 알 수 있습니다. Flog스코어가 엄청 낮기 때문이죠. Car와의 경우도 같습니다.
또한 Frog 스코어 자체가 엄청 낮기 때문이죠. 결국 전체 Loss는 12.9가 됩니다.
그리고 전체 트레이닝 셋의 최종 Loss는 각 트레이닝 이미지의 Loss들의 평균이 되겠습니다.
대략 5.3정도 나오는 걸 볼 수 있습니다.
이것이 의미하는 바는, 우리의 분류기가 5.3점 만큼 이 트레이닝 셋을 구리게 분류하고 있다는 "정량적 지표" 가 되는 것입니다.
질문 있으십니까?
[질문 중]
질문은 바로, "1을 더하는 것"은 어떻게 결정하는 것인지 입니다. (safety margin 이 1이었음)
아무 좋은 질문입니다.
이게 아무 숫자나 막 끼워 넣은 것 같아 보이고
이게 또 손실 함수에서 상수 텀으로 자리잡고 있고 그래서 보기에 불쾌할 수도 있는데요
이게 임의로 선택한 숫자같아 보이긴 하지만, 우리는 사실 손실함수의 "스코어가 정확이 몇인지"는 신경쓰지 않습니다.
우리가 궁금한건 여러 스코어 간의 상대적인 차이인 것입니다.
우리가 관심있어 하는건 오로지 정답 스코어가 다른 스코어에 비해 얼마나 더 큰 스코어를 가지고 있는지 입니다.
행렬 W를 전체적으로 스케일링한다고 생각해 보면 결과 스코어도 이에 따라 스케일이 바뀔 것입니다.
이와 관련된 내용이 온라인 코스 노트에 자세히 나와 있습니다.
그걸 보면 1 이라는게 별 상관 없다는 것을 알게 될 것입니다.
1이라는 파라미터는 없어지고, W의 스케일에 의해 상쇄됩니다.
자세한 내용은 온라인 코스노트를 확인해 주시면 되겠습니다.
그 Loss가 실제무 무슨 일을 하는지를 직관적으로 이해하는 것이 중요하므로 다른 질문들로 다시 접근해 보겠습니다.
만약 Car 스코어가 조금 변하면 Loss에는 무슨 일이 일어날까요?
아이디어 있으십니까?
다들 대답하기 무서워 하는것 같네요
정답?
[대답 하는 학생]
대답은 우리가 Car의 스코어를 조금 바꾸더라고 Loss가 바뀌지 않을 것이라고 대답했습니다.
다시 SVM loss를 상기해보면 이 loss는 오직 정답 스코어와 그 외의 스코어와의 차이만 고려했습니다. 따라서 이 경우에는
Car 스코어가 이미 다른 스코어들보다 엄청 높기 때문에
여기 스코어를 조금 바꾼다고 해도, 서로 간의 간격(Margin)은 여전히 유지될 것이고, 결국 Loss는 변하지 않습니다. 계속 0일 것입니다.
다음 질문은 SVM Loss가 가질 수 있는 최댓/최솟값이 어떻게 될까요?
[대답하는 학생]
잘 못들었습니다?
최솟값은 0이 되겠죠. 왜냐하면 모든 클래스에 걸쳐서
정답 클래스의 스코어가 제일 크면 모든 트레이닝 데이터에서 loss가 0이 될테니깐요
그리고 다시 이 손실 함수가 hinge loss 모양이라는 점을 고려해 보면,
만약 정답 클래스 스코어가 엄청 낮은 음수 값을 가지고 있다고 생각해보면, 아마 Loss가 무한대 일 것입니다.
그러니 최솟값은 0이고 최댓값을 무한대 일 것입니다.
또 한가지는, 파라미터를 초기화하고 처음부터 학습시킬때
보통은 행렬W를 임의의 작은 수로 초기화시키는데, 그렇게되면
처음 학습 시에는 결과 스코어가 임의의 일정한 값을 갖게 됩니다.
그렇다면 만약 모든 스코어 S가 거의 "0에 가깝고" 그리고 "값이 서로 거의 비슷하다면"
Multiclass SVM에서 Loss가 어떻게 될 것 같습니까?
- [학생이 답변]
네, 답변은 "클래스의 수 - 1" 이었습니다.
왜냐면 Loss를 계산할때 정답이 아닌 클래스를 순회합니다. 그러면 C - 1 클래스를 순회하겠죠. 비교하는 두 스코어가 거의 비슷하니
Margin때문에 우리는 1 스코어를 얻게 될 것입니다. 그리고 전에 Loss는 C - 1을 얻게 되는 것이죠
이는 실제로 유용합니다. 특히 "디버깅 전략"으로 말이죠
여러분들이 이런 전략을 가지고 트레이닝을 시작한다면
여러분들은 Loss가 어떻게 될지를 짐작할 수 있게 됩니다.
다시말해 트레이닝을 처음 시작할때 Loss가 C-1이 아니라면
아마 버그가 있는 것이고 고쳐야 할 것입니다.
실제로 아무 유용합니다.
또 다른 질문입니다. SVM Loss는 정답인 클래스는 빼고 다 더했습니다. 그렇다면 정답인 놈도 같이 더하면 어떻게될까요?
만약 다 더하면?
- [학생이 대답]
답은 Loss에 1이 더 증가한다는 것입니다.
일제로 우리가 정답 클래스만 빼고 계산하는 이유는, 일반적으로 Loss가 0이 되야지만
우리가 "아무것도 잃는 것이 없다"고 쉽게 해석할 수 있으며.
Loss에 모든 클래스를 다 더한다고 해서 다른 분류기가 학습되는 것은 아닙니다.
하지만 관례상 정답 클래스는 빼고 계산을 하며, 그렇게 되면 최소 Loss는 0이 됩니다.
또다른 질문입니다. Loss에서 전체 합을 쓰는게 아니라 평균을 쓰면 어떻게 될까요?
- [학생]
네 답은 영향을 미치지 않는다는 것입니다.
클래스의 수는 어짜피 정해져 있으니
평균을 취한다는건 그저 손실 함수를 리스케일 할 뿐입니다.
그러니 상관이 없을 것입니다. 단지 스케일만 변할 뿐입니다.
왜냐하면 우리는 스코어 값이 몇인지는 신경쓰지 않기 때문입니다.
자 이제 또 다른 질문입니다. 만약 우리가 손실함수를 아래와 같이 제곱 항으로 바꾸면 어떻게 될까요?
그럼 결과가 달라질까요 같이질까요?
- [학생]
결과는 달라질 것입니다.
좋은것 과 나쁜것 사이의 트레이드 오프를 비 선형적인 방식으로 바꿔주는 것인데요
그렇게 되면 손실함수의 계산 자체가 바뀌게 됩니다.
실제로도 squared hinge loss를 종종 사용합니다.
이는 여러분들이 손실함수를 설계할때 쓸 수 있는 한가지 방법이 될 수 있습니다.
질문 있나요?
- [학생]
질문은, 왜 굳이 제곱 항을 고려해야 하냐는 것입니다.
손실 함수의 요지는 "얼마나 구린지"를 정량화 하는 것입니다.
그리고 분류자가 다양한 종류의 실수를 저지르고 있다면,
어떻게 해야 이 분류기가 만드는 다양한 Loss들 마다 상대적으로 패널티를 부여할 수 있을까요?
만약 Loss에 제곱을 한다면 이제 "엄청 엄청 안좋은 것들" 은 정말로 "곱절로 안좋은 것" 이 됩니다.
그러니 정말로 나빠지게 되는겁니다.
마치 우리가 심하게 잘못 분류되는 것들을 정말 원하지 않는 것이 됩니다.
반면에 hinge loss를 사용하게 되면
실제로 "조금 잘못된 것" 과 "많이 잘못된 것" 을 크게 신경쓰지 않게 되는 것입니다.
만약 "많이 잘못된 것" 이 있다면 우리는 Loss를 증가시키고 학습을 통해 Loss를 줄일 것인데
그 줄어드는 Loss의 량이 "조금 잘못된 것"이던 "많이 잘못된 것" 이던 큰 차이가 없을 것입니다.
제가 좀 개략적으로 말씀드리긴 했지만
둘 중 어떤 loss를 선택하느냐는 우리가 에러에 대해 얼마나 신경쓰고 있고, 그것을 어떻게 정량화 할 것인지에 달려있습니다.
그리고 이 문제는 실제 여러분들이 손실함수를 만들때 고려해야만 하는 것입니다.
왜냐하면 손실 함수라는 것이 여러분이 여러분들의 알고리즘에게 "어떤 에러를 내가 신경쓰고 있는지"
그리고 "어떤 에러가 트레이드오프 되는 것인지" 를 알려주는 것입니다.
그러니 실제로는 여러분들의 문제에 따라서 손실함수를 잘 설계하는 것은 엄청 중요하다고 할 수 있습니다.
여기 Numpy 코드가 있습니다. 아마 여러분들도 첫 과제에서 이처럼 구현해야 할 것입니다.
여기서 말씀드리고 싶었던건 Numpy를 사용하면 코드 몇줄이면 이 손실 함수를 코딩할 수 있다는 것입니다.
여기 재미있는 기법을 하나 볼 수 있습니다.
max로 나온 결과에서 정답 클래스만 0으로 만들어 주는 것이죠 (margin[y] = 0)
이것은 굳이 전체를 순회할 필요가 없게 해주는 일종의 vectorized 기법입니다.
전체 합을 구할때 제외하고 싶은 부분만 0으로 만들어줍니다.
아마 과제를 할 때 아주 유용할 것입니다.
자 이제 손실 함수에 대한 또 다른 질문이 있습니다.
운이 좋게도 W가 0인 정답을 찾았다고 해 봅시다. 잃은 것이 전혀 없는 것이고, 여러분이 이긴 것입니다!
그렇다면 여기서 질문입니다. 이렇게 Loss가 0이 되게 하는 W가 유일하게 하나만 존재하는 것일까요?
- [학생]
맞습니다. 다른 W도 존재합니다.
특히나 좀 전에도 언급했듯이 W의 스케일은 변합니다.
그렇다면 W에 두배를 한다고 해도 변하지 않을 것입니다. (double double U 니까 quad U인가요?, 모르겠네요)
[웃음]
어쨋든 그 W도 역시 Loss가 0 이겠죠
그래서 이것의 구체적인 예로서,
좋아하는 예제로 돌아갈 수 있습니다.
어쩌면 숫자를 통해 일할 수도 있습니다.
나중에 조금,
만약 여러분에게 W와 2W가 있다면, 정답 스코어 와 정답이 아닌 스코어의 차이의 마진(margins)또한 두배가 될 것입니다.
그러니 모든 마진(margins)이 이미 1보다 더 크다면, 우리가 두배를 한다고 해도
여전히 1보다 클 것이고 Loss가 0 일 것입니다.
여기서 아주 흥미로운 점이 있습니다.
손실 함수 라는 것이. 분류기에게 우리는 어떤 W를 찾고 있고 어떤 W에 신경쓰고 있는지를 말해주는 것이라면
이것은 조금 이상합니다. "불일치" 하는 점이 있습니다.
다양한 W중 Loss가 0인 것을 선택하는 것은 모순입니다.
왜냐하면 여기에서는 오직 데이터의 loss에 대해서만 신경쓰고 있고
그리고 분류기에게 트레이닝 데이터에 꼭 맞는 W를 찾으라고 말하는 것 과 같습니다.
하지만 실제로 우리는 트레이닝 데이터에 얼마나 꼭 맞는지는 전혀 신경쓰지는 않습니다.
기계학습의 핵심은, 트레이닝 데이터를 이용해서 어떤 분류기를 찾는 것인데
그 분류기는 테스트 데이터에 적용할 것이기 때문입니다.
그러니 우리는 트레이닝 데이터의 성능에는 관심이 있는 것이 아니라
우리는 테스트 데이터에서의 성능에 관심이 있는 것입니다.
그러니 분류기에게 트레이닝 데이터의 Loss에만 신경쓰라고 한다면
아마 좋지 않은 상황이 벌어질 것입니다.
아마 분류기가 이해할 수 없는 행동을 할 수도 있습니다.
좀 더 구체적인 예를 들어 보겠습니다.
하지만 지금의 예는, 지금까지 배웠던 선현 분류기에 대한 것은 아니고 기계학습에서 다루는 좀 더 일반적인 개념이라 보시면 됩니다.
여기 파란 점의 데이터 셋이 있습니다.
이제 우리가 할 일은 어떤 곡선을 가지고 저 파란색 점들에 피팅시키는 것입니다.
우리가 분류기에게 유일하게 말할 수 있는 것은, 그저 트레이닝 데이터에 핏 하게 하라고 말하는 것입니다.
그러면 분류기는 모든 트레이닝 데이터를 완벽하게 분류해 내기 위해서 구불구불한 곡선을 만들 것입니다.
하지만 이러면 안좋습니다. 왜냐하면 이 상황에서는 "성능" 에 대해서 전혀 고려하지 않았기 때문입니다.
우린 항상 테스트 데이터의 성능을 고려해야 합니다.
만약 새로운 데이터가 들어오게 되면
앞서 만든 구불구불한 곡선은 완전히 틀리게 됩니다.
사실 우리가 의도했던건 초록색 선인 것입니다.
완벽하게 트레이닝 데이터에 핏한 복잡하고 구불 구불한 곡선을 원한 것이 아닌 것입니다.
이는 기계학습에서 가장 중요한 문제 입니다.
그리고 보통 이를 해결하는 방법을 통틀어 Regularization이라 합니다.
손실 함수에 항을 하나 추가합니다.
"Data Loss Term"에서는 분류기가 트레이닝 데이터에 핏하게 하고
또한, 보통 손실 함수에 "Regularization term"을 추가하는데
이는 모델이 좀 더 단순한 W를 선택하도록 도와줍니다.
"단순하다" 라는 개념은 우리가 해결해야 할 문제나 모델에 따라 조금씩 달라집니다.
과학 계에서 널리 쓰이는 "오컴의 면도날" 이라는 말이 있습니다.
만약 여러분들에게 다양한 가설들을 가지고 있고, 그 가설들 모두가 어떤 현상에 대해 설명 가능하다면
그럼 여러분은 일반적으로 "더 단순한 것" 을 선호해야 한다는 것입니다.
왜냐하면 좀 "더 일반적인(더 단순한)" 것이 미래1에 일어날 현상을 잘 설명할 가능성이 더 높기 때문입니다.
그리고 기계학습에서는 이런 류의 직관을 써먹기 위해서 "Regularization penalty"라는 것을 만들어 냈습니다.
Regularization은 보통 R로 표기합니다.
그렇게 되면, 일반적인 손실 함수의 형태는 두가지 항을 가지게 됩니다.
Data loss와 Regularization loss입니다.
그리고 하이퍼파라미터인 람다(lambda)도 생겼습니다. 두 항 간의 트레이드오프입니다.
지난 강의에서 하이퍼파라미터와 크로스벨리데이션을 배웠습니다.
여기 Regularization의 하이퍼파라미터 람다는 실제로 여러분들이 모델을 훈련시킬 때 고려해야 할 중요한 요소 중 하나입니다.
질문 있나요?
- [학생 질문]
질문은 바로
Wx + lambda R 이란 것이 도대체 뭐길래 구불구불한 곡선을 직선으로 바꿔 준다는 것입니까? 라는 것입니다.
사실 그 부분을 깊에 다루려면 너무 오래걸려서 여기에서는 언급하려 하지 않았습니다.
하지만 짐작해 볼 수 있습니다. 여러분들에게 회귀문제가 있습니다. 일종의 다항식 기저 함수로 나타낼 수 있겠죠
일반적으로 모델은 고차 다항식을 이용해서 문제를 풀려 할 것입니다.
여기에 어떤 regression term을 추가하면 모델이 데이터를 핏 할 떄 저차 다항식을 더 선호하도록 하게 하는 것입니다.
그러니 여러분은 Regularization의 두 가지 역할에 대해 생각해 볼 수 있습니다.
하나는 여러분의 모델이 더 복잡해 지지 못하도록 하는 것이고
또는 모델에 soft penalty를 추가하는 것으로 보는 것입니다. 모델은 여전히 더 복잡한 모델이 될 가능성이 있는 것입니다.
이 다항식의 예라면, 더 복잡한 차수에도 접근할 수 있는 것이지요
하지만 이 soft한 제약을 하나 추가하면, "만약 너가 복잡한 모델을 계속 쓰고싶으면, 이 penalty를 감수해야 할 거야!" 라는 것과 같습니다.
이것으로 인해 완전한 선형 분류문제가 되진 않겠지만
많은 사람들이 "Regularization"에 대해 이런 식으로 떠올립니다.
실제로 Regularization에는 여러 종류가 있습니다.
가장 보편적인 것은 L2 Regularization입니다. Weight decay라고도 하죠.
이 외에도 다양한 것이 많습니다.
L2 Regularization은 가중치 행렬W에 대한 Euclidean Norm입니다.
간혹 squared norm이라고도 하죠
또는 1/2 * squared norm 을 사용하기도 합니다. 미분이 더 깔끔해집니다.
하지만 L2 Regularization의 주요 아이디어는 가중치 행렬 W의 euclidean norm에 패널티를 주는 것입니다.
그리고 L1 regularization도 보게 될 것인데, 이는 L1 norm으로 W에 패널티를 부과하는 것입니다.
L1 Regularization을 하면 행렬 W가 희소행렬이 되도록 합니다.
그리고 Elastic net regularization도 있습니다. L1과 L2를 짬뽕해놓은 것이죠
간혹 Max norm regularization도 보게 될 것입니다. L1, L2 대신에 max norm을 쓰는 것이죠
하지만 이런 regularization은 딥러닝에서만 쓰는 것이 아니라 많은 기계학습 분야를 통틀어서 자주 사용하는 것입니다.
심지어는 더 광범위하게 최적화 할 수도 있습니다.
Regularization 기법 중 특히나 딥러닝에 관련된 기법들을 앞으로 배우게 될 것입니다.
예를 들어, 앞으로 배울 Dropout이나 Batch Normalization , Stochastic depth와 같은 최근 아주 쩌는 것들이죠
Regularization은 모델이 트레이닝 데이터셋에 완벽히 핏 하지 못하도록 모델의 복잡도에 패널티를 부여하는 방법입니다.
질문 있나요?
[말하는 학생]
질문은, "L2 Regularization이 모델이 복잡한지 아닌지를 어떻게 알(측정) 수 있냐" 는 것입니다.
고맙게도 다음에 할 내용이 바로 그것입니다.
여기 한 예시가 있습니다. 트레이닝 데이터 x가 있고 서로 다른 두개의 W가 있습니다.
x는 4줄짜리 벡터이고, 여기에 두개의 서로 다른 W에 대해 생각해 볼 수 있겠습니다. x = [1 1 1 1]
하W중 하나는 처음에만 1이 있고 나머지 세 원소는 0입니다. w1 = [1 0 0 0]
다른 하나는 원소가 모두 0.25입니다. w2 = [0.25 0.25 0.25 0.25]
이걸 가지고 Linear classification을 할때 우리는 x와 w의 내적을 구합니다.(dot product)
Linear classification의 관점에서 w1와 w2는 같습니다.
왜냐하면 x와의 내적이 서로 같기 때문이죠.
여기서 문제는, w1, w2중 L2 regression이 더 선호하는것은 어떤 것일까요?
L2 regression은 w2를 더 선호할 것입니다. 왜냐면 L2 regression에서는 w2가 더 norm이 작기 때문이죠
그러니 L2 Regression은 분류기의 복잡도를 상대적으로 w1와 w2중 어떤 것이 더 coarse한지를 측정합니다. (값이 매끄러워야함)
Linear classification에서 W가 의미하는 것은, "얼마나 x가 Output Class와 닮았는지" 입니다.
그러니 L2 Regularization이 말하고자 하는것은 x의 모든 요소가 영향을 줬으면 하는 것입니다.
그러니 변동이 심한 어떤 입력 x가 있고 그 x의 특정 요소에만 의존하기 보다
모든 x의 요소가 골고루 영향을 미치길 원한다면, L2 Regularization을 통해 더 강인해 질 수 있을 것입니다.
반면 L1 Regularization의 경우에는 정 반대입니다.
L1 Regularization을 쓰게 되면 W2보다는 W1을 더 선호하게 됩니다.
L1 Regularization은 "복잡도"를 다르게 정의합니다.
L1 Regularization은 가중치 W에 0의 갯수에 따라 모델의 복잡도를 다룹니다.
그러니 "복잡도" 을 어떻게 정의하느냐, 그리고 L2 Regularization은 "복잡도"을 어떻게 측정하느냐는
우리가 어떤 문제를 가지고 있으냐에 따라 다릅니다.
그러니 여러분이 어떤 문제가 있고, 어떤 모델이 있고 데이터가 있을때
여러분은 이 문제에서 "복잡하다"는 것을 어떻게 정의할 지를 반드시 고민해야 할 것입니다.
질문 있나요?
- [학생]
네 맞습니다.
w1과 w2의 경우에는 L1의 값이 같습니다.
하지만 여러분은 L1 Regularization이 선호하는 w1를 손쉽게 만들어 볼 수 있습니다.
L1에 대한 일반적인 직관은 "일반적으로 L1은 sparse한 solutions을 선호한다"는 것입니다.
그리고 이것은 W의 요소 중 대부분이 0이 되게 할 것입니다.
그렇게 때문에 L1이 "복잡하다"고 느끼고 측정하는 것은 0이 아닌 요소들의 갯수가 될 수 있습니다.
반면 L2의 경우에는 W의 요소가 전체적으로 퍼져있을 때 "덜 복잡하다" 라고 생각하게 됩니다.
그러니 선택은 여러분들의 데이터와 문제에 달려 있습니다.
좀 더 나아가서, 여러분이 Bayesian에 대해 잘 안하면 L2 Regularization을 사용하다는 것을
parameter vector로 Gaussian prior를 쓰는 MAP inference로 볼 수도 있다는 것입니다.
해당 하는 내용이 CS229의 과제에 있었던 것으로 기억하지만 이 강의에서는 더이상 다루지는 않을 것입니다.
지금 우리는 multi-class SVM Loss에 대해 깊게 알아보고 있는 중입니다.
질문 있나요?
[학생 질문]
질문은, Regularization된다고 Hypothesis class가 변하지 않을 것이라는 것입니다.
그리고 Linear classifier 라는 것이 변하지 않을 것이라는 것입니다.
이 Polynomial regression의 예는 확실이 Linear regression은 아닙니다.
입력의 차수가 증가하는 상황에서의 Linear regression으로 볼 수는 있습니다.
이 경우에는 우리가 많은 polynomial coefficients를 사용하고 싶지는 않다는 것을 의미하는 것입니다.
이런 식으로 생각해 보시면 될 것 같습니다.
여러분이 polynomial regression을 한다고 했을때
f(x)=A0 * 1 + A1 * x + A2 * x^2 + A3 * x^3 와 같은 식으로 나타낼 수 있겠죠
이 경우 우리가 가진 parameters는 A집합이 되겠습니다.
A에 penalty를 준다는 것은 polynomial의 차원이 더 적어지도록 하는 것입니다.
Polynomial regression의 경우가 아니라면 실제로 A의 형태로 파라미터가 생기진 않을 것입니다.
여러분이 사용하고 싶은 다른 파마미터를 설정하게 될 것입니다.
그러나 그것은 일반적인 생각입니다,
hypothesis class 중에 더 간단한 것을 선택하기 위해서 우리는 model에 Penalty를 주는 것입니다.
아직 헷갈리면 개인적으로 다시 질문해 주시기 바랍니다.
지금까지 Multi-class SVM Loss에 대해 알아보았습니다. 그리고 부차적으로 또 하나가 있습니다.
지금까지 본 것은 SVM Loss를 Multi class로 확장시킨 아주 일반적인 손실함수일 뿐입니다.
여러 문헌을 찾아보게 되면 몇가지 다른 공식들도 존재합니다.
하지만, 적어도 딥러닝에서는 그런 여러가지 손실함수들이 사실은 거의 비슷하게 동착합니다.
그렇기 때문에, 이 수업에서는 지금까지 배웠던 multi-class SVM loss만 가지고 이야기할 것입니다.
하지만 당연히 여러분이 생각해볼만한 여러 다양한 손실 함수들이 존재합니다.
multi-class SVM loss 외에도 인기있는 것이 하나 있습니다.
딥러닝에서 자주쓰는 Multinomial logistic regression, 즉 softmax입니다.
사실 딥러닝에서는 이걸 더 많이 씁니다.
하지만 몇가지 이유가 있어 두번째로 소개해 드립니다.
multi-class SVM loss에서 우리는 스코어 자체에 대한 해석은 고려하지 않았습니다.
어떤 분류문제가 있고 어떤 모델 F가 각 클래스에 해당하는 10개의 숫자를 출력할때면
mulfi-class SVM의 경우에 우리는 그 스코어 자체는 크게 신경쓰지 않았습니다.
우린 단지 정답 클래스가 정답이 아닌 클래스들 보다 더 높은 스코어를 내기만을 원했죠
그 이상, 스코어 자체가 실제로 의미하는 것에는 관심이 없었습니다.
하지만 Multinomial Logistic regression의 손실함수는 스코어 자체에 추가적인 의미를 부여합니다.
그리고 특히, 저 수식을 이용해서 스코어를 가지고 클래스 별 확률 분포를 계산하게 될 것입니다.
여기에서는 softmax라고 불리는 함수를 쓸 것입니다.
스코어를 전부 이용하는데, 스코어들에 지수를 취해서 양수가 되게 만듭니다.
그리고 그 지수들의 합으로 다시 정규화 시킵니다.
그래서 softmax 함수를 거치게 되면 우리는 결국 확률 분포를 얻을 수 있고
그것은 바로 해당 클래스일 확률이 되는 것입니다.
확률이기 때문에 0에서 1 사이의 값이고
모든 확률들의 합은 1이 됩니다.
이제 한번 해석을 해봅시다.
이게 우리가 스코어를 가지고 계산한 확률 분포가 있습니다.
이제 이 확률값을 실제 값과 비교해 볼 것입니다.
만약 이미지가 고양이라면 실제 고양이 일 확률은 1이 됩니다.
그리고 나머지 클래스의 확률은 0이 됩니다.
내그러니 우리가 지금 하고자 하는 것은 softmax에서 나온 확률이
정답 클래스에 해당하는 클래스의 확률을 1로 나타내게 하는 것입니다.
이런 식은 다양하게 사용될 수 있습니다. 예를 들어 두 분포 간의 KL divergence라던가
아님 이 식은 MLE로 볼 수도 있습니다.
하지만 결국 우리가 원하는 것은 정답 클래스에 해당하는 클래스의 확률이 1에 가깝게 계산되는 것입니다.
그렇게 되면 Loss는 "-log(정답클래스확률)" 이 될 것입니다.
여기에 이것저것 들어가서 헷갈릴 수도 있지만
한번 잘 생각해보면 우린 지금 확률이 1이 되길 원하고 있습니다.
그리고 log는 단조 증가 함수이죠, 이런식으로 증가하죠
그리고 log를 최대화시키는 것이 그냥 확률값을 최대화 시키는 것 보다 쉽습니다. 그러니 우리는 log를 씁니다.
log가 단조증가함수 라고 했었죠 그러니 정답 클래스인, log P 를 최대화 시키는건, lop P가 높았으면 좋겠다는 것인데
그런데 손실 함수는 "얼마나 좋은지" 가 아니라 "얼마나 구린지" 를 측정하는 것이기 때문에 log에 마이너스를 붙힙니다.
이제 SVM의 손실함수는 -log(P(정답클래스)) 로 나타내게 됩니다.
요약을 해보자면
스코어가 있으면, softmax를 거치고, 나온 확률 값이 -log를 추가하면 됩니다.
이제 이게 어떻게 생겼는지 구체적인 예시로 확인해 보겠습니다.
다시 고양이 예제로 돌아가 봅시다. 여기 Linear classifier 의 출력으로 나온 스코어가 있습니다.
이 스코어는 이전에 SVM Loss에서의 예제와 같은 값입니다.
하지만 이제는 스코어 자체를 Loss로 쓰기보다는 이제 스코어를 지수화 시킬 것입니다.
그래서 그들은 모두 긍정적입니다,
그리고 합이 1이 되도록 정규화 시켜 줍니다.
그리고 정답 스코어에만 -log를 씌여줍니다.
이걸 softmax라고 합니다. 또는 다항 로지스틱 회귀라고도 하죠. (multinomial logistic regression)
이전에 여러분이 직관을 얻을 수 있도록 multi-class SVM Loss 몇 가지를 던졌었는데요.
Softmax loss를 이해하는데도 그 질문이 도움이 될 것입니다.
그럼 질문은
softmax loss의 최댓값과 최솟값을 얼마일까요?
여기 log도 있고 합치는 것도 있고 해서 좀 헷갈릴수도 있습니다.
정답은 바로 Loss의 최솟값은 0 이고 최댓값은 무한대입니다.
확률 분포를 한번 생각해 보자면, 우리는 정답 클래스의 확률은 1이 되길 원하고 정답이 아닌 클래스는 0 이 되길 원합니다.
이런 식으로 생각해보면, log안에 있는 어떤 값은 결국 1이 되어야 하는 것입니다.
정답 클래스에 대한 Log 확률이기 때문에 Log(1) = 0 이고, -log(1) 또한 0입니다.
그러므로 고양이를 완벽히 분류했다면 Loss는 0이 될 것입니다.
그렇다면 Loss가 0이 되려면 실제 스코어는 어떤 값이어야 할까요?
아마 정답 스코어는 극단 적으로 높아야 할 것입니다. 거의 무한대에 가깝게 말이죠
여기에서는 지수화를 하고 정규화를 하기 때문에
우리가 확률 1(정답) 과 0(그외) 를 얻으려면, 정답 클래스의 스코어는 +무한대 가 되어야 하고, 나머지는 -무한대 가 되어야 합니다.
컴퓨터는 무한대 계산을 잘 못하기 때문에, Loss가 0인 경우는 절대 없을 것입니다.(유한 정밀도 때문에)
하지만 이론적 해석을 가미하면 0 은 "이론적으로 최소 Loss이다" 라고 보면 됩니다.
최대 손실은 최댓값이 없습니다.
만약 정답 클래스의 확률이 0이고, 거기 -log를 취하면 [-log(0)]
log(0)는 음의 무한대가 되고 따라서 -log(0)는 양의 무한대가 됩니다.
정말 안좋은 경우이겠죠
하지만 이러한 경우 또한 발생하지는 않을 것입니다. 왜냐하면 확률이 0이 되려면 e^syi가 0이 되어야 하는데
그게 가능한 경우는 정답 클래스의 스코어가 음의 무한대일 일 때 뿐이기 떄문입니다.
다시한번 말씀드리자만 "유한 정밀도" 를 가지고는 최댓값(무한대) 최솟값(0)에 도달할 수는 없습니다.
또한 multi-class SVM 손실함수를 이야기할때 디버깅을 할 수 있는 방법에 대해서는 말씀드렸는데요
softmax도 같습니다.
만약 S가 모두 0 근처에 모여있는 작은 수일때 Loss는 어떻게 될까요?
정답?
- [학생]
맞습니다. -log(1/C) 가 되겠죠
log는 분모와 분자를 뒤집을 수 있으니까 -log(1/C)는 log(C)가 됩니다.
softmax를 사용할 때 첫 번째 interation에서 해볼만한 아주 좋은 디버깅 전략입니다.
log(c)가 아니면 뭔가 잘못된 것입니다.
이제 지금까지 배운 두 손실함수를 한번 비교해 보겠습니다.
Linear classification의 설정은 둘다 같은 조건입니다.
행렬 W와 입력을 못하는 것은 둘다 같습니다.
다만 두 손실 함수의 차이점은 바로 "얼마나 구린지" 를 측정하기 위해 스코어를 해석하는 방식이 조금 다르다는 것입니다.
SVM에서는 정답 스코어와, 정답이 아닌 스코어 간의 마진(margins)을 신경썼습니다.
반면 softmax (crossentropy) 는 확률을 구해서 -log(정답클래스) 에 신경을 씁니다.
간혹 이것을.... 아니다 이부분은 건너 뛰겠습니다.
[웃음]
두 손실 함수 간의 차이에 대한 흥미로운 질문이 하나 있습니다.
[어떤 얘기 하다가 다른 예시로 돌림] 여기 있는 예제는 무시하세요
multi-class SVM loss의 예시를 다시 생각해보면
car클래스에서 car의 스코어가 다른 클래스보다 훨씬 높았습니다.
그래서 car스코어를 조금 바꾼다고 해서 SVM Loss가 변하거나 하진 않았죠
왜냐면 SVM loss는 오직 정답과 그 외 클래스의 마진이 얼마나 되는지 에만 관심이 있기 때문입니다.
이런 점에서 softmax loss는 상당히 다릅니다.
softmax는 언제나 확률은 1로 만드려고 노력할 것입니다.
그러니, 정답 스코어가 충분히 높고, 다른 클래스 스코어가 충분히 낮은 상태에서도
softmax는 최대한 정답 클래스에 확률을 몰아 넣으려고 할 것이고
정답 클래스는 무한대로, 그 외의 클래스는 음의 무한대로 보내려 할 것입니다.
그리고 그것은 두 손실 함수 간의 흥미로운 차이점 입니다.
SVM의 경우에는 일정 선(margins)을 넘기만 하면 더이상 성능 개선에 신경쓰지 않습니다.
반면 softmax는 더더더더더좋게 성능을 높이려 할 것입니다.
두 손실 함수 간의 흥미로운 차이점인 것입니다.
실제 딥러닝 애플리케이션에서 두 손실 함수 간의 성능 차이는 엄청나게 크진 않습니다만
그렇긴 해도 차이를 알고 있는 것은 유용할 것입니다.
자 이제 지금까지 한 것들을 정리해 보자면
우선 우리에게 데이터 셋 x와 y가 있습니다.
우선 입력 x로부터 스코어를 얻기 위해 Linear classifier를 사용 할 것입니다.
softmax, svm loss와 같은 손실함수를 이용해서, 모델의 예측값이 정답 값에 비해 "얼마나 구린지"를 측정합니다.
그리고 모델의 "복잡함" 과 "단순함" 을 통제하기 위해 손실 함수에 regularization term을 추가할 것입니다.
지금까지 우리가 Supervised leraning이라 부르는 것에 관한 전반적인 개요를 배워 보았습니다.
우리가 딥러닝에서 배울 내용은, 어떤 엄청 복잡한 함수 f를 정의하고
그리고는 파라미터 값이 주어졌을때 알고리즘이 얼마나 "구리게" 동작하고 있는지 측정할 손실 함수를 작성하고
그리고 모델이 복잡해 지는 것을 어떻게 막을지에 대한 Regularization term을 추가합니다.
그리고 그걸 모두 합쳐서, 최종 손실 함수가 최소가 되게 하는 가중치 행렬이자 파라미터인 행렬W를 구하게 되는 것입니다.
자 이제 다음 질문은, 실제로 어떻게 해야 하는 것일까요? 어떻게 실제 Loss를 줄이는 W를 찾을 수 있는 걸까요?
이 질문은 우리를 "최적화" 라는 주제로 이끌어 줍니다.
최적화를 하고 있다는걸 상상해보면, 우리가 엄청 큰 계곡을 걷고 있는 것 같습니다.
여러분은 다양한 산과 계곡과 시내가 있는 엄청 큰 골짜기를 거닐고 있는 것입니다.
그리고 "산"과 "계곡" 과 같은 풍경들이 바로 파라미터 W입니다.
그리고 여러분이 이 골짜기를 돌아다니는 한 사람인 것이고,
내가 있는 곳의 "높이" 가 바로 Loss 인 것입니다. Loss는 W에 따라 변하게 되고, 우리는 W를 찾아야 합니다.
여러분의 임무는 이곳을 돌아다니는 한 사람이 되어
어떻게든 이 골짜기의 밑바닥을 찾아내는 것입니다.
하지만 그런 문제들은 일반적으로 엄청 어렵습니다.
만약 여러분이 엄청 똑똑해서 손실함수와 regularization 등 모든 것들의 속성 하나 하나를 다 분석해 냈다면
어쩌면 제가 골짜기의 밑바닥으로 마법같이 순간이동할 수 있는 minimizer를 만들어낼 수도 있겠 습니다만
하지만 실제로 NN을 사용하면 "예측 함수", "손실함수", "Regularizer" 같은 것들이 엄청 크고 복잡해 져서
어떤 명시적인 솔루션을 만들어내서 최적의 솔루션(minima)를 직접 얻어내는 것은 불가능 할 것입니다.
그래서 실제로 우리는 다양한 "iterative한 방법"들을 씁니다.
이 방법들은 임의의 지점에서 시작해서 점차적으로 성능을 향상시키는 방법입니다.
우선, 가장 먼저 생각해 볼 수 있는 단순한 방법은 임의 탐색(random search) 입니다.
임의로 샘플링한 W들을 엄청 많이 모아놓고 Loss를 계산해서 어떤 W가 좋은지를 살펴보는 것입니다.
미리 말씀드리자면 정말 구린 알고리즘이고 여러분들은 절대로 이 방법은 쓰지 마셔야 합니다.
하지만 한번쯤 "상상"해 볼 법한 방법이긴 합니다.
실제로 해 볼수도 있긴 합니다. 임의 탐색으로 Linear Classfier을 학습시킬 수 있습니다.
CIFAR-10에서 클래스는 10개이니까 임의 확률은 10%가 되고, 무작위 시행을 거치게 되면,
소가 뒷걸음질 치는 격으로 어떤 W를 구해 볼 수 있는데 이 예시에서는 15%의 정확도를 보이는군요
10개중 하나 찍는것 보단 좋지만, 최신 알고리즘의 성능 (SOTA)이 95%라는 점을 생각하면, 격차가 좀 많이 나죠
실제로는 이렇게 하지 마시고 이런 방법도 "가능은 하다" 정도로만 알고 넘어가시면 되겠습니다.
실제로 더 나은 전략은 지역적인 기하학적 특성을 이용하는 것입니다. (local geometry)
만일 여러분이 이 계곡을 걷고있는 사람이라면
여러분이 계곡의 밑바닥이 어디인지 두 눈으로 확인할 수는 없을 것입니다.
하지만 두 발로 느끼고 그곳의 지형을 파악할 수 있을 것입니다.
제가 여기에 이렇게 서있다면 어떤 방향으로 가야 내려갈 수 있을까요?
여러분은 두 발로 땅의 경사를 느끼고, 어느 방향으로 가야 내려갈 수 있을지를 알 수 있을 것입니다.
이제 그 방향으로 한발자국 내딛고는 조금 걸어내려 가다가는, 다시 두 발로 느끼고 방향을 다시 찾아봅니다.
이렇게 반복하다 보면 결국 여러분은 골짜기를 다 내려갈 수 있을 것입니다.
이 알고리즘이 엄청 쉬워보이지만, 실제로 정말 잘 동작합니다. 만약 여러분이 세부 사항을 잘 파악한다면 말이죠
이 방법은 우리가 NN이나 Linear classifer 같은 것들을 훈련시킬 때 일반적으로 사용하는 방법입니다.
지금까지는 대략적인 감만 설명해 드린 것입니다.
그렇다면 경사(slope)는 무엇일까요?
미분 수업이 기억나시나요? 1차원 공간에서 경사(slope)는 어떤 함수에 대한 미분값입니다.
1차원 함수 f가 있다고 해봅시다. f(x) = y x를 입력으로 받으면, 출력은 어떤 커브의 높이겠죠
곡선의 일부를 구하면 기울기를 계산할 수 있습니다.
이제 어떤 점(x)에서의 경사, 즉 도함수(derivative)를 계산해보면
작은 스텝 , h가 있고 이 스텝 간의 함수 값의 차이를 비교해 본다면 f(x+h) - f(x)
그리고 그 스텝사이즈를 0으로 만들면 (h->0) 그것이 바로 어떤 점에서의 이 함수의 경사가 됩니다.
그리고 이 수식은 다변수함수(multi-variable functions) 에서로 확장시킬 수 있습니다.
실제로 x는 스칼라(값이 하나) 가 아니라 벡터 입니다.
x가 벡터이기 때문에 위의 개념을 다변수로 확장시켜야 합니다.
다변수인 상황에서의 미분으로 일반화시켜보면 gradient이고 gradient는 벡터 x의 각 요소를 편도함수들의 집합입니다.
gradient의 모양은 x와 같습니다. (입력이 3개면 gradient도 3개)
그리고 gradient 의 각 요소가 알려주는 것은 바로 "우리가 그쪽으로 갈때 함수 f의 경사가 어떤지" 라는 것입니다.
gradient를 통해 그런 유용한 정보를 얻을 수 있는 것입니다. gradient는 편도함수들의 벡터입니다.
gradient의 방향은 함수에서 "가장 많이 올라가는 방향" 이 됩니다.
반대로 생각해보면, gradient의 반대 반향이라면 "가장 많이 내려갈 수 있는 방향" 이 되는 것입니다.
그렇다면, 여러분이 만약에 특정 방향에서 얼마나 가파른지 알고싶으면 어떻게 해야 할까요?
이는 그 방향의 유닛벡터와 gradient벡터를 내적할 것과 같습니다.
gradient는 매우 중요합니다. 왜냐하면 gradient가 함수의 어떤 점에서의 선형 1차근사 함수를 알려주기 때문입니다.
그래서 실제로 많은 딥러닝 알고리즘들이 gradient를 계산하고
그 gradient를 여러분들이 파라미터 벡터를 반복적으로 업데이트할 때 사용하는 것입니다.
컴퓨터로 이 gradient를 써먹을 수 있는 가장 단순한 방법 중 하나는
유한 차분법(finite difference methods)를 이용하는 것입니다.
다시 gradient의 극한 식으로 돌아가 봅시다.
자 여기 왼쪽은 보면 파라미터 벡터 W가 있습니다.
이 W를 사용하면 1.25정도의 Loss를 가지는군요
우리가 할 일은 gradient "dW" 를 구하는 것입니다. W와 모양은 같습니다.
그리고 gradient의 각 요소가 말해주는 것은 우리가 그쪽 방향으로 아주 쬐끔 이동했을 때 Loss가 어떻게 변하는지 입니다.
이걸 간단하게 유한 차분법으로 계산해 봅시다.
일단 W가 있고, 지금 할 일은 W의 첫번째 요소(0.34) 에 아주 작은 값 h를 더해 보는 것입니다.
그리고 loss를 다시 계산해 봅니다.
여기에서 알 수 있는 것은, 우리가 첫 번째 요소를 조금 움직이면 Loss가 1.2534에서 1.25322로 감소한다는 것입니다.
이제 극한 식을 이용해서 FDM으로 근사시킨 gradient를 구합니다.
두 번째 요소에서도 이를 반복할 수 있겠습니다.
이제 다시 첫 번째 요소의 값은 원래대로 돌려놓고 두 번째 요소를 아주 조금 증가시킵니다.
그리고 다시 Loss를 계산하고 FDM을 이용해서 두 번째 요소 gradient의 근사치를 계산해 볼 수 있습니다.
이런 세번째에도 하고 계속 반복합니다.
이건 실제로는 정말 끔질한 방법입니다. 시간이 엄청 오래걸리거든요
이 함수 f가 CNN같이 엄청 큰 함수였다면. 엄청 오래 걸렸을 것입니다.
그리고 파라미터 W가 여기서는 10개뿐이 없지만
엄청 크고 깊은 신경망이라면 파라미터가 수천 수억개 일 수도 있습니다.
따라서 실제로는 이런식으로 gradient를 계산하지 않습니다.
왜냐면 gradient 하나를 구하려고 수천개의 함수값을 일일이 다 계산해야 하기 떄문입니다.
이건 엄청 느리고 안좋습니다.
아마도 여러분들이 살면서 한번쯤은 미적수업을 들은적이 있을 것입니다.
여기 이 두분들 덕분에, 우리는 단지 손실함수를 적어놓기만 하고
미분이라는 마법의 헤머를 두드리기만 하면 gradient가 계산되어 나옵니다.
해적적으로 푸는 것이 수치적으로 푸는 것 보다 더 효율적입니다.
일단 더 정확하기도 할 뿐더러, 식 하나로 계산할 수 있기 때문에 계산 도 훨씬 더 빠릅니다.
다시 W 그림으로 돌아가 봅시다.
W 의 모든 원소를 순회하는 것이 아니라
gradient를 나타내는 식이 뭔지만 먼저 찾아내고
그걸 수식으로 내타내서 한번에 gradient dW를 계산해 버리는 것입니다.
실제로 이 방법이 훨씬 더 좋습니다.
요약하자면, 앞서 말한 수치적인 gradient는 간단하고 그럴듯 하긴 하지만
실제로는 사용하지 않는다는 것입니다.
실제 gradient 계산을 구현할때는 분석적인 방법을 이용합니다.
하지만 흥미로운 점은 이런 수치적 gradient도 디버깅 툴로는 유용할 수 있다는 것입니다.
우리가 Loss의 gradient를 계산하는 코드를 짜고 있다고 해봅시다.
그것을 어떻게 디버깅하시겠습니까?
여러분이 작성한 미분 코드가 잘 작동하는지를 어떻게 확인하실 것입니까?
그런 상황에 흔히들 쓰는 방법은 바로 이 수치적 gradient를 사용하는 것입니다.
유닛 테스트의 일종으로 여러분들의 코드를 확인할 수 있습니다.
하지만 수치적인 방법은 엄청 느리고 부정확 하므로 이를 디버깅에 이용하고자 한다면
파라미터의 스케일을 줄이는 편이 좋습니다. 그래야 디버깅이 오래 걸리지 않을 것입니다.
여러분만의 gradient 계산 코드를 짤때 쓸만한 유용한 디버깅 전략 하나는 소개시켜 드렸습니다.
실제로도 정말 많이 사용하고, 여러분들도 과제에서 사용하게 될 것입니다.
일단 우리가 gradient를 계산하는 방법을 알고 나면
이 세 줄짜리 간단한 알고리즘은 엄청 크고 복잡하고 싶은 신경망 알고리즘을 어떻게 학습시킬지에 대한 핵심 아이디어를 담 고 있습니다.
Gradient Descent에서는 우선 W를 임의의 값으로 초기화합니다.
그리고 Loss와 gradient를 계산한 뒤에 가중치를 gradient의 반대 방향으로 업데이트합니다.
gradient가 함수에서 증가하는 방향이기 때문에 -gradient를 해야 내려가는 방향이 되는 것입니다.
그러니 -gradient 방향으로 아주 조금씩 이동할 것이고 이걸 영원히 반복하다 보면 결국에는 수렴할 것입니다.
그렇게 되면 엄청 행복하겠지요...
하지만 스텝 사이즈는 하이퍼 파라미터 입니다. 스텝 사이즈는 그 -gradient 방향으로 얼마나 나아가야 하는지를 알려줍니다.
스텝사이즈는 Learning rate라고도 하며, 실제 학습을 할때 여러분이 정해줘 야 하는 가장 중요한 하이퍼파라미터 중 하나입니다.
저의 경우에는 트레이닝을 시작할때 Leraning Rate는 제가 가장 먼저 체크하는 하이퍼파라미터입니다.
모델 사이즈라던지 Regularization 의 강도라던지 하는 것들은 우선 나중으로 미뤄두고
Learning rate를 올바르게 정해주는 것을 가장 먼저 합니다.
여기 그림을 보면 2차원 공간의 아주 간단한 예시가 있습니다.
여기 그릇처럼 보이는 것이 손실합수 입니다.
가운데 빨간 부분이 낮은 Loss인 것이고
테두리의 파란영역과 초록 영역은 Loss가 더 높은 곳입니다. 피해가야 겠죠
자 이제 임의의 점에 W를 설정해 두겠습니다.
이제 우리는 -gradient를 계산할 것이고 이를 통해 우리는 결국 가장 낮은 지점에 도달할 것입니다.
그리고 이걸 계속 반복하게 되면 아마도 결국은 정확한 최저점에 도달하게 될 것입니다.
실제로 한번 봅시다.
우선 임의의 점에서 시작해서 매번 조금씩 계속 이동하는 것입니다.
그리고 파라미터가 최저점으로 휘어져 들어가는 것을 볼 수 있습니다.
우리가 낮은 loss를 원했기 때문에 이것은 정확히 우리가 바라던 것입니다.
하지만 지금까지 본 예제는 아주 단순한 방법입니다. 매 스텝마다 -gradient의 방향으로만 이동한 뿐이죠
하지만 다음 몇 강의동안 여러분은 더 쩌는 스텝을 볼 수 있을 것입니다. Update Rule 이라고도 하는 방법이죠
여러 스텝을 한번에 고려하는 더 쩌는 방법들이 존재합니다.
기본적인 Gradient descent보다 실제 학습시에 더 좋은 성능을 보이는 것들입니다.
맛보기로, 같은 문제를 푸는 다른 개쩌는 방법들을 몇가지 보여드리겠습니다.
검정색은 이전에 본 것과 같은 스텝인 것이고 나머지 둘중 뭐가 뭔지 기억이 잘 안나지만
어쨋든 나머지 두개는 좀 더 쩌는 Update rules입니다.
이 방법들은 다음 스텝에 현재의 gradient 정보를 이용합니다.
하나는 momentum을 이용한 것이고 다른 하나는 Adam optimizer를 이용한 방법입니다.
저 자세한 사항은 다음 수업에서 다루도록 하겠습니다.
그 방법들의 핵심은, Gradient Descent라는 기본적인 알고리즘을 사용하고 있고
다음 스텝을 결정하기 위해서 이전의 모든 스텝의 gradient정보를 이용하는 것입니다.
그래서 gradient 정보를 정확히 어떻게 이용할 것이냐 에 따라서 여러 Update rule이 존재하긴 하지만
결국 기본적인 알고리즘은 바로 매 스텝 아래로 내려가는 것입니다.
우리가 배워야 할 또 한가지가 있습니다.
손실 함수를 정의했던 것을 생각해보면, Loss는 각 트레이닝 샘플을 분류기가 얼마나 "구리게" 분류하는지를 계산하는 것이였고
그리고 전체 Loss는 전체 트레이닝 셋 Loss의 평균으로 사용했습니다.
하지만 실제로는 N이 엄청 커 질수도 있습니다.
첫 강의에서 말했던 ImageNet 데이터셋을 생각해보면 N은 130만개 입니다.
따라서 Loss를 계산하는건 정말 오래 걸리는 작업이 됩니다.
아마 수백만번의 계산이 필요한 것입니다. 그래서 그것은 정말로 느릴 수 있습니다.
사실 gradient 는 선형 연산자 이기 때문에
실제 gradient를 계산하는 과정을 살펴보면, Loss는 그저 각 데이터 Loss의 Gradient의 합이라는 것을 알 수 있습니다.
그러니 gradient를 한번 더 계산하려면 , N개의 전체 트레이닝 셋 을 한번 더 돌면서 계산해야 하는 것입니다.
N이 100만 이라면 엄청 느리게 되겠죠. W가 일일이 업데이트 되려면 엄청나게 많은 시간을 기다려야 할 것입니다.
그래서 실제로는 stochastic gradient descent 라는 방법을 씁니다.
전체 데이터 셋의 gradient과 loss를 계산하기 보다는
Minibatch라는 작은 트레이닝 샘플 집합으로 나눠서 학습하는 것입니다.
Minibatch는 보통 2의 승수로 정하며 32, 64, 128 을 보통 씁니다.
따라서 이 작은 minibatch를 이용해서 Loss의 전체 합의 "추정치"와 실제 gradient의 "추정치"를 계산하는 것입니다.
그래서 stochastic 하다는 것은 Monte Carlo Method의 실제 값 추정 방법과 유사하다고 볼 수 있습니다.
알고리즘이 더 쩔어 졌지만 코드는 여전히 4줄이면 충분합니다.
이제는 임의의 minibatch를 만들어내고, minibatch에서 Loss와 Gradient를 계산합니다. 그리고 W를 업데이트합니다.
Loss의 "추정치" 와 Gradient의 "추정치" 를 사용하는 것입니다.
그리고 앞으로, 이 좀 더 간지나는 Update Rules이 정확히 어떻게 여러 gradients들을 통합시키는지 알아 볼 것입니다.
그리고 SGD는 거의 모든 DNN알고리즘에 사용되는 기본적인 학습 알고리즘입니다.
Linear classifier를 이용해서 SGD로 어떻게 이것을 학습 시키는 지에 대한 웹 데모를 준비했습니다만
지난 시간에 웹데모를 실패했기 때문에 실제 링크를 열지 않고 비디오로 보여드리겠습니다.
[웃음]
온라인에서 한번 접속해 보세요
Linear classifier와 이를 Gradient descent로 학습 시키는 것에 대한 직관을 얻을 수 있습니다.
여기 왼쪽에는 세개의 카테고리 클래스를 볼 수 있습니다.
여기 초록, 파랑, 빨간 점들이 있고 이 점들이 트레이닝 샘플입니다.
그리고 각 클래스에 해당하는 결정 경계를 그려 놨습니다. 배경 색은 해당하는 지역입니다.
뿐만 아니라 방향도 있는데, 이 방향은 갹 세개의 클래스 스코어가 증가하는 방향입니다.
그리고 접속해서 실제로 해보면 실제 W를 조정할 수가 있습니다. W를 조절하면 결정 경계가 회전하는 것을 볼 수 있습니다.
Bias를 조정하면 결정경계가 회전하지 않고 위아래로만 움직입니다.
스텝도 만들어 놨습니다. W를 업데이트도 할 수 있죠
슬라이드바를 사용해서 스텝사이즈를 변경할 수 있습니다.
스텝 사이즈를 크게 잡으니 , 지금 GD를 돌리고 있는데 결정 경계가 데이터에 핏하려고 날뛰고 있군요
이제 날뛰지 않는군요. 그리고 손실 함수도 실시간으로 바뀔 수 있습니다.
여러 SVM과 softmax 를 사용할 수 있습니다.
그리고 여러분이 다양한 손실 함수를 적용해 보게 되면 손실 함수들이 일반적으로 같은 일을 하고 있다는 것을 알 수 있습니다.
나눠진 지역들이 알고리즘 마다 비슷하긴 하지만
결국 각각이 어떻게 학습이 종료되는지를 확인해보고
여러 요소들의 trade-off를 따져보게 되면 조금씩 다르다는 것을 알 수 있습니다.
그러니 GD를 통해 Linear classifier를 학습시키는게 실제로 어떻게 생겼는지를 보면서 직관을 얻으셨으면 좋겠습니다.
이제 좀 다른 얘기를 해볼까 합니다.
이미지의 특징에 관한 것입니다.
지금까지 Linear classifier에 대해 이야기해 보았습니다. 실제 Raw 이미지 픽셀을 입력으로 받는 방식이었죠
지난 강의에서 말씀 드렸듯이 이런 방법은 좋은 방법은 아닙니다.
Multi-Modality 와 같은 것들 때문이죠 (말 머리 두개)
실제로는 영상 자체를 입력으로 사용하는 것은 성능이 좋지 않습니다.
그래서 DNN이 유행하기 전에 주로 쓰는 방법은 두가지 스테이지를 거치는 방법이었습니다.
첫번 째는, 이미지가 있으면 여러가지 특징 표현을 계산하는 것입니다.
이런 특징 표현은 이미지의 모양새와 관련된 것일 수 있습니다.
그리고 여러 특징 표현들은 한데 연결시켜(Concat) 하나의 특징 벡터로 만듭니다.
그러면 이 특징 벡터가 Linear classifier의 입력으로 들어가는 것입니다.
여기에서의 모티브는 , 여기 그림과 같은 트레이닝 셋이 있다고 해 보면
빨간 점들이 가운데 있고 그 주변에 파란 점들이 있죠
이런 데이터 셋의 경우에는 Linear한 결정 경제를 그릴 방법이 없는 것입니다.
이런 예시를 지난 강의에서 더 살펴 봤었습니다.
만약 우리가 적절하게 특징 변환을 해본다면, 이경우에는 극좌표계로 바꾼 것입니다.
그 복잡하던 데이터가, 변환 후에 선형으로 분리가 가능하게 바뀌었습니다.
실제로도 Linear classifier로 완벽하게 분리할 수 있습니다.
이런 기법들은 여러분의 문제를 풀 수 있도록 하려면 어떤 특징 변환이 필요한가 를 알아내는 것들입니다.
이미지의 경우 픽셀들을 극좌표계로 바꾸는 것은 전혀 말이 안되는 일이지만
극좌표계로 변환하는 것을 일종의 특징 변환이라 생각한다면 말이 되는 것입니다.
그리고 이것은 실제로 분류기에 Raw 이미지를 넣는것 보다 성능이 더 좋을지도 모릅니다.
특징 변환의 한 예를 들어보자면 컬러 히스토그램이 있습니다.
이미지에서 Hue 값만 뽑아서 모든 픽셀을 각 양동이에 넣는 것입니다.
한 필셀은 해당하는 색의 양동이에 넣고 각 양동이에 들어있는 픽셀의 개수를 세는 것입니다.
이는 이미지가 적체적으로 어떤 색인지를 알려줍니다.
이 개구리의 예를 보면 초록색이 많은걸 알 수 있습니다. 자주색이나 붉은색은 별로 없습니다.
실제로 사용하는 간단한 특징 벡터라고 볼 수 있습니다.
NN이 뜨기 전에 인기있었던 또 다른 특징 벡터중 하나는 바로 Histogram of oriented gradients(HOG) 입니다.
첫 강의를 생각해보면 Hubel 과 Wiesel이 이런 Oriented edges가 인간의 시각시스템에서 정말 중요하다고 했습니다.
HOG도 그와 같은 직관을 가지고 있으며 Local orientation edges를 측정합니다.
실제로 하는 일을 보면 이미지가 있으면 8x8로 픽셀을 나눕니다.
그리고 이 8x8 픽셀 지역 내에서, 가장 지배적인 edge의 방향을 계산하고
그리고 edge directions을 양자화해서 양동이에 넣는 것입니다.
그리고 다양한 edge oreirentations에 대한 히스토그램을 계산하는 것입니다.
그러면 전체 특징 벡터는, 각각의 모든 8x8 지역들이 가진 "edge orientation에 대한 히스토그램" 이 되는 것입니다.
이전에 봤던 컬러 히스토그램이랑은 좀 다르죠
컬러 히스토그램은 이미지 전체적으로 어떤 색이 있는지를 나타냈습니다.
반면 HOG는 이미지 내에 전반적으로 어떤 종류의 edge정보가 있는지를 나타냅니다.
이미지를 여러 부분으로 지역화해서, 지역적으로 어떤 edge가 존재하는지도 알 수 있습니다.
그래서 이 개구리의 경우를 보면 이파리 위에 앉아있는 것을 볼 수 있습니다.
그리고 이파리들은 주로 대각선 edge를 가지고 있습니다.
그리고 실제 HOG를 시각화해 보면 이파리 부분에 많은 대각 edge가 있다는 것을 알 수 있습니다.
이것이 바로 HOG의 특징표현이 가지고 있는 것입니다.
HOG는 영상 인식에서 정말 많이 활용한 특징벡터입니다. 엄청 오래전에 사용했던 것이 아닙니다.
또 하나의 특징 표현이 있는데 바로 bag of words입니다.
이 아이디어는 자연어처리(NLP)에서 영감을 받은 것인데요
어떤 문장이 있고, BOW에서 이 문장을 표현하는 방법은
바로 문장의 여러 단어의 발생 빈도를 세서 특징 벡터로 사용하는 것입니다.
이 직관을 그대로 이미지에 적용한 것입니다.
하지만 BOW를 적용하려고 하는데 이미지에 적용하려니 쉬운 문제가 아니였습니다.
그래서 "시각 단어(visual words)"라고 하는 우리만의 용어를 정의해야 했습니다.
여기에서는 2단계의 과정이 있습니다.
엄청 많은 이미지를 가지고, 그 이미지들은 임의대로 조각냅니다. 그리고 그 조각들을 K-means와 같은 알고리즘으로 군집화합니다.
이미지내의 다양한 것들을 표현할 수 있는 다양한 군집들을 만들어 내는 것입니다.
오른쪽 예를 보면, 이것은 이미지들에서 다양한 이미지 패치를 뽑아내서 군집화 시켜 놓은 실제 예시입니다.
군집화 단계를 거치고나면, 시각 단어(visual words)는 빨간색, 파랑색, 노랑색과 같은 다양한 색을 포착해냅니다.
분만 아니라 다양한 종류의 다양한 방향의 oriented edges또한 포착할 수 있습니다.
그리고 이건은 매우 흥미롭습니다. 왜냐하면 이런 edges들을 데이터 중심적인 방법을 통해 얻어낸 것이기 때문입니다.
이런 시각 단어(visual words) 집합인 Codebook을 만들고 나면
그러면 어떤 이미지가 있으면, 이 이미지에서의 시각 단어들의 발생 빈도를 통해서 이미지를 인코딩 할 수 있는 것입니다.
그리고 이는 이 이미지가 어떻게 생겼는지에 대한 다양한 정보를 제공하는 것입니다.
그리고 BOW는 Fei-Fei 교수님께서 대학원시절에 만든 것입니다.
여러분이 지금까지 봤던 것들이 실제로 엄청 오래전에 쓰인 것이 아닙니다.
나중에 설명한 내용이긴 하지만 Image classification의 pipleline은 이렇게 생겼습니다.
5~10년 전까지만 해도 이미지를 입력받으면 BOW나 HOG와 같은 다양한 특징 표현을 계산하고,
계산한 특징들을 한데 모아 연결해서, 추출된 그 특징들을 Linear classifier의 입력으로 사용했습니다.
제가 어느정도 단순화시키긴 했지만, 대부분은 일반적으로 이런 직관이라고 보시면 되겠습니다.
특징이 한번 추출되면 feature extractor는 classier를 트레이닝하는 동안 변하지 않습니다.
트레이닝 중에는 오직 Linear classifier만 훈련이 됩니다.
그리고 CNN이나 DNN으로 넘어가 보자면 실제로 크게 다르지 않습니다.
유일하게 다른점이 있다면 이미 만들어 놓은 특징들을 쓰기 보다는 데이터로부터 특징들을 직접 학습하려 한다는 것입니다.
터그렇기 때문에 raw 픽셀이 CNN에 그대로 들어가고 여러 레이어를 거쳐서 데이터를 통한 특징 표현을 직접 만들어냅니다.
따라서 Linear classifier만 훈련하는게 아니라 가중치 전체를 한꺼번에 학습하는 것입니다.
그럼 다음시간에는 CNN에 대해 더 심도깊에 살펴볼 것이고 역전파(backpropagarion) 또한 알아볼 것입니다.